package com.ecloud.service.security.config;

import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.ecloud.common.data.dynamic.DynamicDataSource;
import com.ecloud.common.data.transaction.DynamicTransactionFactory;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

/**
 * 数据库连接池配置<br>
 *
 * @author LiuGangQiang Create in 2020/03/02
 */
@Configuration
public class DataSourceConfiguration {

    /**
     * 主数据源配置
     *
     * @author LiuGangQiang Create in 2021/04/27
     * @return {@link DataSource}
     */
    @Primary
    @Bean(DynamicDataSource.MASTER)
    @ConfigurationProperties(prefix = "spring.datasource.hikari")
    public DataSource masterDataSource() {
        HikariDataSource dataSource = new HikariDataSource();
        return dataSource;
    }

    /**
     * 读取动态数据源配置
     *
     * @author LiuGangQiang Create in 2021/05/01
     * @return {@link HikariConfig}
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.dynamic")
    public HikariConfig hikariConfig() {
        return new HikariConfig();
    }

    /**
     * 动态数据源配置
     *
     * @author LiuGangQiang Create in 2021/04/27
     * @return {@link DataSource}
     */
    @Bean
    public DynamicDataSource dynamicDataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource() {

            @Override
            public DataSource registerDataSource(String key) {
                if (StringUtils.isNotBlank(key)) {
                    /* TODO 这里处理多数据源动态注册 */
                }
                return null;
            }
        };
        Map<Object, Object> dataSourceMap = new HashMap<>();
        /* 默认添加主数据源 这里可以在项目启动时初始化多个数据源 */
        dataSourceMap.put(DynamicDataSource.MASTER, masterDataSource());
        /* 主数据源设为默认数据源 */
        dynamicDataSource.setDefaultTargetDataSource(masterDataSource());
        /* 设置多数据源 */
        dynamicDataSource.setDataSources(dataSourceMap);
        return dynamicDataSource;
    }

    /**
     * 配置连接工厂
     *
     * @author LiuGangQiang Create in 2021/04/27
     * @return {@link MybatisSqlSessionFactoryBean}
     */
    @Bean
    @ConfigurationProperties(prefix = "mybatis-plus")
    public MybatisSqlSessionFactoryBean sqlSessionFactoryBean() {
        MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
        /* 注入分页插件 */
        sessionFactory.setPlugins(paginationInterceptor());
        /* 注入动态数据源 */
        sessionFactory.setDataSource(dynamicDataSource());
        /* 注入动态数据源事务管理器 */
        sessionFactory.setTransactionFactory(new DynamicTransactionFactory());
        return sessionFactory;
    }

    /**
     * 配置分页插件
     *
     * @author LiuGangQiang Create in 2021/04/27
     * @return {@link MybatisPlusInterceptor}
     */
    @Bean
    public MybatisPlusInterceptor paginationInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }

    /**
     * 配置事务管理器
     *
     * @author LiuGangQiang Create in 2021/04/27
     * @return {@link PlatformTransactionManager}
     */
    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dynamicDataSource());
    }
}